/**
 * 
 */
package com.patternity.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Represents a a model made of types and relations between them.
 * 
 * @author Cyrille.Martraire
 */
public class SimpleModel implements Model, ModelBuilder {

	private final Map<String, Element> elements = new HashMap<String, Element>();

	private final List<Relation> relations = new ArrayList<Relation>();

	// Fluent interface
	@Override
	public Element addElement(final Element element) {
		elements.put(element.getName(), element);
		return element;
	}

	// @Override
	@Override
	public Element addElementIfNotThere(final Element element) {
		final Element existing = elements.get(element.getName());
		if (existing != null) {
			return existing;
		}
		elements.put(element.getName(), element);
		return element;
	}

	@Override
	public Element getElement(final String name) {
		return elements.get(name);
	}

	@Override
	public Iterable<Element> elements() {
		return Collections.unmodifiableCollection(elements.values());
	}

	@Override
	public Iterable<Relation> relations() {
		return Collections.unmodifiableCollection(relations);
	}

	@Override
	public List<Element> getSubTypes(final Element superElement) {
		return new ArrayList<Element>();
	}

	// Fluent interface
	@Override
	public Relation addRelation(final Relation relation) {
		relations.add(relation);
		return relation;
	}

	@Override
	public String toString() {
		final StringBuilder sb = new StringBuilder("Model");
		sb.append("\nTypes");
		for (final Element type : elements.values()) {
			sb.append("\n\t");
			sb.append(type);
		}
		sb.append("\nRelations");
		for (final Relation relation : relations) {
			sb.append("\n\t");
			if (relation.getFrom() instanceof Element) {
				final Element from = (Element) relation.getFrom();
				sb.append(from.getName());
			} else {
				sb.append(relation.getFrom());
			}
			sb.append(" - ");
			sb.append(relation.getName());
			sb.append(" - ");
			if (relation.getTo() instanceof Element) {
				final Element to = (Element) relation.getTo();
				sb.append(to.getName());
			} else {
				sb.append(relation.getTo());
			}
		}
		return sb.toString();
	}

}
